package com.ning.cloud.framework.security.interceptor;

import com.alibaba.fastjson2.JSON;
import com.ning.cloud.common.constant.CommonConstant;
import com.ning.cloud.common.enums.ErrorCode;
import com.ning.cloud.common.util.Response;
import com.ning.cloud.framework.security.UserContext;
import com.ning.cloud.framework.security.config.JwtProperties;
import com.ning.cloud.framework.security.config.SecurityConfig;
import com.ning.cloud.framework.security.dto.AuthUserDTO;
import com.ning.cloud.framework.security.util.JwtTokenUtil;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

/**
 * 由网关gateway解析token获到的用户信息 传入下游服务的头部中，由此拦截器解析头部用户信息
 *
 * @todo：security模块需要从common模块中剥离出来，解耦
 *
 */
@Component
@Slf4j
public class UserAuthInterceptor implements HandlerInterceptor {


    @Resource
    JwtTokenUtil jwtTokenUtil;

    @Resource
    JwtProperties jwtProperties;

    @Resource
    SecurityConfig securityConfig;

//    @Override
//    public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object handler) throws Exception {
//
//        String requestRri = request.getRequestURI();
//
//        //获取request token
//        String jwtToken = null;
//        String bearerToken = request.getHeader(jwtProperties.getHeader());
//        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(jwtProperties.getTokenPrefix())) {
//            jwtToken = bearerToken.substring(jwtProperties.getTokenPrefix().length());
//        }
//        log.info("获取到的bearer token:{}", bearerToken);
//
//        AuthUserDTO authUserDTO = jwtTokenUtil.parseToken(jwtToken);
//        if (authUserDTO == null) {
//            Response response = Response.error(ErrorCode.UNAUTHORIZED);
//            this.writeJson(JSON.toJSONString(response), httpServletResponse);
//            return false;
//        }
//        return true;
//    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object handler) throws Exception {

        //①、从网关层获取到的登录用户信息，由头部获取
        String userHeader = request.getHeader(CommonConstant.HEADER_LOGIN_USER);
        String token = request.getHeader(CommonConstant.HEADER_TOKEN);
        log.info("获取到的登录用户信息：{}", userHeader);
        log.info("获取到的token：{}", token);
        AuthUserDTO authUserDTO = null;
        if (StringUtils.isNotBlank(userHeader)) {
            //解码
            userHeader = URLDecoder.decode(userHeader, StandardCharsets.UTF_8);
            // 将用户信息转换为UserInfo对象
            authUserDTO = JSON.parseObject(userHeader, AuthUserDTO.class);
        }

        //②、直接从bearer token中解析jwttoken获取到用户信息,兼容不经过网关直接请求的场景
        if (authUserDTO == null) {
            authUserDTO = this.getAuthUserFromBearerToken(request);
        }

        //不需要鉴权的接口
        String requestUri = request.getRequestURI();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        //true表示不需要登录
        boolean noAuthUri = securityConfig.getIgnoreUrls().stream().anyMatch(url -> antPathMatcher.match(url, requestUri));

        if (!noAuthUri && authUserDTO == null) {
            Response response = Response.error(ErrorCode.UNAUTHORIZED);
            this.writeJson(JSON.toJSONString(response), httpServletResponse);
            return false;
        }
        if (authUserDTO != null) {
            UserContext.setAuthUser(authUserDTO);
        }

        return true;
    }

    /**
     * 从bearer token解析用户信息
     * 说明：此方式没有经过网关，直接从头部Authorization bearer token中解析用户信息
     * @param request
     * @return
     */
    private AuthUserDTO getAuthUserFromBearerToken(HttpServletRequest request) {
        //获取request token
        String bearerToken = request.getHeader(jwtProperties.getHeader());
        String jwtToken = null;
        if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(jwtProperties.getTokenPrefix())) {
            jwtToken = bearerToken.substring(jwtProperties.getTokenPrefix().length());
        }
        log.info("获取到的bearer token:{}", bearerToken);

        if (StringUtils.isBlank(jwtToken)) {
            return null;
        }

        AuthUserDTO authUserDTO = jwtTokenUtil.parseToken(jwtToken);
        return authUserDTO;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mv) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception ex) throws Exception {
        UserContext.remove();
    }


    public static void writeJson(String json, HttpServletResponse resp){
        PrintWriter pw = null;
        try {
            resp.setContentType("application/json");
            resp.setCharacterEncoding("utf8");
            pw = resp.getWriter();
            pw.print(json);
            pw.flush();
            pw.close();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            pw.close();
        }
    }

}
